package userFileModuleApi

import (
	"KumquatDrivesServices/common/res"
	"KumquatDrivesServices/enums"
	"KumquatDrivesServices/global"
	"KumquatDrivesServices/model"
	"KumquatDrivesServices/utils"
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

type moveFileOrFolderRequest struct {
	FileIds  []model.SnowflakeIdType `json:"fileIds" binding:"required"`
	FolderId model.SnowflakeIdType   `json:"folderId" binding:"required"`
}

func (UserFileModuleApi) MoveFileOrFolder(c *gin.Context) {
	var req moveFileOrFolderRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		logrus.Errorf("MoveFileOrFolder ShouldBindJSON err: %v", err)
		res.FailWithCode(res.PARAM_ERR, c)
		return
	}
	userId := utils.GetUserId(c)
	if userId == 0 {
		logrus.Errorf("MoveFileOrFolder userId==0")
		res.FailWithCode(res.SYS_ERR, c)
		return
	}
	//检查文件是否在目标文件夹中
	var count int64
	if err := global.DB.Model(&model.FileModel{}).
		Where("id in (?) and file_pid =? and user_id =?",
			req.FileIds, req.FolderId, userId).Count(&count).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logrus.Errorf("MoveFileOrFolder err: %v", err)
		res.FailWithCode(res.SYS_ERR, c)
		return
	}
	if count > 0 {
		res.FailWithCode(res.FILE_CANT_MOVE_TO_ORIGINAL_DIR, c)
		return
	}
	//检查目标文件夹是否存在
	if req.FolderId != 1 {
		var folerCount int64
		if err := global.DB.Model(&model.FileModel{}).
			Where("id=? and user_id=? and is_folder=? and del_flag=?",
				req.FolderId, userId, enums.Folder, enums.Normal).
			Count(&folerCount).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
			res.FailWithCode(res.PARAM_ERR, c)
			return
		}
	}
	//查询目标文件夹里的文件
	var targetFolderFiles []model.FileModel
	if err := global.DB.
		Where("file_pid=? and user_id=? and del_flag=?", req.FolderId, userId, enums.Normal).
		Find(&targetFolderFiles).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
		logrus.Errorf("MoveFileOrFolder err: %v", err)
		res.FailWithCode(res.SYS_ERR, c)
		return
	}
	targetFileInfoMap := make(map[string]model.FileModel, len(targetFolderFiles))
	for _, targetFileInfo := range targetFolderFiles {
		targetFileInfoMap[targetFileInfo.FileName] = targetFileInfo
	}
	//查询被移动的文件
	var selectedFileList []model.FileModel
	if err := global.DB.Where("id in (?) and user_id=? and del_flag=?", req.FileIds, userId, enums.Normal).
		Find(&selectedFileList).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			res.FailWithCode(res.PARAM_ERR, c)
			return
		}
		logrus.Errorf("MoveFileOrFolder err: %v", err)
		res.FailWithCode(res.SYS_ERR, c)
		return
	}
	if len(selectedFileList) == 0 {
		res.FailWithCode(res.PARAM_ERR, c)
		return
	}
	tx := global.DB.Begin()
	//重命名文件和移动文件
	for _, selectedFileInfo := range selectedFileList {
		updateMap := make(map[string]interface{})
		updateMap["file_pid"] = req.FolderId
		if targetFileInfo, exists := targetFileInfoMap[selectedFileInfo.FileName]; exists && selectedFileInfo.IsFolder == targetFileInfo.IsFolder {
			newFileName := utils.Rename(selectedFileInfo.FileName)
			updateMap["file_name"] = newFileName
		}
		if err := tx.Model(&selectedFileInfo).Where("id=? and user_id=? and del_flag=?",
			selectedFileInfo.ID, userId, enums.Normal).Updates(updateMap).Error; err != nil {
			tx.Rollback()
			logrus.Errorf("MoveFileOrFolder update err: %v", err)
			res.FailWithCode(res.SYS_ERR, c)
			return
		}
	}
	if err := tx.Commit().Error; err != nil {
		logrus.Errorf("MoveFileOrFolder commit err: %v", err)
		res.FailWithCode(res.SYS_ERR, c)
		return
	}
	res.OkWithData(res.EmptyData, c)
}
